/*
******************************************************************************************************* 
**  Copyright (C) 2019, 苏州检易生物科技有限公司 
**  All rights reserved. 
** 
**  FileName:       	can.c
**  Description:	
**  Author:        	 
**  Version				v0.1
**  Date:           	2019-05-30
**	Function List： 
**  History:         
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                              	调试开关
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "can.h"
#include "log_console.h"
/*
*********************************************************************************************************
*                                              	宏定义
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                              	函数原型声明
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                              	全局变量定义
*********************************************************************************************************
*/
static uint8_t		m_tx_buf[CAN_MAX_SIZE];
/*
*********************************************************************************************************
*                                              	模块静态变量定义
*********************************************************************************************************
*/
static bsp_can_t m_bsp_can1;
static bsp_can_t m_bsp_can2;
/*
*********************************************************************************************************
*                                              	函数定义
*********************************************************************************************************
*/
bsp_can_t*	bsp_can_init(FDCAN_GlobalTypeDef* can,uint16_t can_id,uint32_t baudrate)
{
	ASSERT(can);
	GPIO_InitTypeDef GPIO_Initure;
	RCC_PeriphCLKInitTypeDef FDCAN_PeriphClk;
	
	__HAL_RCC_FDCAN_CLK_ENABLE();
	__HAL_RCC_GPIOA_CLK_ENABLE();
	__HAL_RCC_GPIOB_CLK_ENABLE();

	FDCAN_PeriphClk.PeriphClockSelection=RCC_PERIPHCLK_FDCAN;
	FDCAN_PeriphClk.FdcanClockSelection=RCC_FDCANCLKSOURCE_PLL;
	HAL_RCCEx_PeriphCLKConfig(&FDCAN_PeriphClk);
	
	bsp_can_t* p_handle;
	
	switch((uint32_t)can)
	{
		case (uint32_t)FDCAN1:
		{
			p_handle = &m_bsp_can1;
			p_handle->hal_can_handle.Instance = can;
			GPIO_Initure.Pin=GPIO_PIN_12|GPIO_PIN_11;
			GPIO_Initure.Mode=GPIO_MODE_AF_PP;
			GPIO_Initure.Pull=GPIO_PULLUP;
			GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
			GPIO_Initure.Alternate=GPIO_AF9_FDCAN1;
			HAL_GPIO_Init(GPIOA,&GPIO_Initure);
			break;
		}
		case (uint32_t)FDCAN2:
		{
			p_handle = &m_bsp_can2;
			p_handle->hal_can_handle.Instance = can;
			GPIO_Initure.Pin=GPIO_PIN_5|GPIO_PIN_6;
			GPIO_Initure.Mode=GPIO_MODE_AF_PP;
			GPIO_Initure.Pull=GPIO_PULLUP;
			GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
			GPIO_Initure.Alternate=GPIO_AF9_FDCAN2;
			HAL_GPIO_Init(GPIOB,&GPIO_Initure);
			break;
		}
		default:return NULL;
	}
	
	p_handle->can_id = can_id;
	FDCAN_HandleTypeDef* p_hal_handle = &p_handle->hal_can_handle;
//	m_bsp_can.tx_callback=pfn_tx_cb;
//	m_bsp_can.rx_callback=pfn_rx_cb;

	FDCAN_FilterTypeDef FDCAN_RXFilter;
	
	HAL_FDCAN_DeInit(p_hal_handle);
//	p_hal_handle->Instance=FDCAN1;
	p_hal_handle->Init.FrameFormat=FDCAN_FRAME_CLASSIC;
	p_hal_handle->Init.Mode=FDCAN_MODE_NORMAL;
	p_hal_handle->Init.AutoRetransmission=DISABLE;                 //关闭自动重传！传统模式下一定要关闭！！！
	p_hal_handle->Init.TransmitPause=DISABLE;                      //关闭传输暂停
	p_hal_handle->Init.ProtocolException=DISABLE;                  //关闭协议异常处理
	if(baudrate == 500)
	{
		p_hal_handle->Init.NominalPrescaler=10;                     //分频系数
		p_hal_handle->Init.DataPrescaler=10;                     //分频系数
	}
	else if(baudrate == 1000)
	{
		p_hal_handle->Init.NominalPrescaler=5;                     //分频系数
		p_hal_handle->Init.DataPrescaler=5;                     //分频系数
	}
	else if(baudrate == 250)
	{
		p_hal_handle->Init.NominalPrescaler=20;                     //分频系数
		p_hal_handle->Init.DataPrescaler=20;                     //分频系数
	}
	else
		return NULL;
	
	p_hal_handle->Init.NominalSyncJumpWidth=8;                 //重新同步跳跃宽度
	p_hal_handle->Init.NominalTimeSeg1=31;                      //tsg1范围:2~256
	p_hal_handle->Init.NominalTimeSeg2=8;                      //tsg2范围:2~128
	p_hal_handle->Init.DataSyncJumpWidth=8;                 //重新同步跳跃宽度
	p_hal_handle->Init.DataTimeSeg1=31;                      //tsg1范围:2~256
	p_hal_handle->Init.DataTimeSeg2=8;                      //tsg2范围:2~128
	p_hal_handle->Init.StdFiltersNbr=1;                            //标准信息ID滤波器编号
	p_hal_handle->Init.ExtFiltersNbr=0;                            //扩展信息ID滤波器编号
	p_hal_handle->Init.RxFifo0ElmtsNbr=0;                          //接收FIFO0元素编号
	p_hal_handle->Init.RxFifo0ElmtSize=FDCAN_DATA_BYTES_8;         //接收FIFO0元素大小：8字节
	p_hal_handle->Init.RxFifo1ElmtsNbr=0;                          //接收FIFO0元素编号
	p_hal_handle->Init.RxFifo1ElmtSize=FDCAN_DATA_BYTES_8;         //接收FIFO0元素大小：8字节
	p_hal_handle->Init.RxBuffersNbr=0;                             //接收缓冲编号
  p_hal_handle->Init.RxBufferSize = FDCAN_DATA_BYTES_8;
	p_hal_handle->Init.TxEventsNbr=0;                              //发送事件编号
	p_hal_handle->Init.TxBuffersNbr=0;                             //发送缓冲编号
	p_hal_handle->Init.TxFifoQueueMode=FDCAN_TX_FIFO_OPERATION;    //发送FIFO序列模式
	p_hal_handle->Init.TxElmtSize=FDCAN_DATA_BYTES_8;              //发送大小:8字节
	if(can == FDCAN1)
	{
		p_hal_handle->Init.RxFifo0ElmtsNbr=32;
		p_hal_handle->Init.MessageRAMOffset = 0;
		p_hal_handle->Init.TxFifoQueueElmtsNbr = 32;
		FDCAN_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0;
		
	}
	else if(can == FDCAN2)
	{
		p_hal_handle->Init.RxFifo1ElmtsNbr=32;
		p_hal_handle->Init.MessageRAMOffset = 0x406;
		p_hal_handle->Init.TxFifoQueueElmtsNbr = 32;
		FDCAN_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO1;
	}
	if(HAL_FDCAN_Init(p_hal_handle)!=HAL_OK)
		return NULL;
 
	FDCAN_RXFilter.IdType=FDCAN_STANDARD_ID;                       //标准ID
	FDCAN_RXFilter.FilterIndex=0;                                  //滤波器索引                   
	FDCAN_RXFilter.FilterType=FDCAN_FILTER_MASK;                   //滤波器类型
//	FDCAN_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0;           //过滤器0关联到FIFO0  
	FDCAN_RXFilter.FilterID1=0x0000;                               //32位ID
	FDCAN_RXFilter.FilterID2=0x0000;                               //如果FDCAN配置为传统模式的话，这里是32位掩码
	if(HAL_FDCAN_ConfigFilter(p_hal_handle,&FDCAN_RXFilter)!=HAL_OK) 
		return NULL;//滤波器初始化
	
	HAL_FDCAN_Start(p_hal_handle);
	

//	uint8_t buff[8]={0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x02};
//	bsp_can_send(0x80, buff,8);
	return p_handle;
}
can_err_t		bsp_can_cb_reg(bsp_can_t* handle,bsp_can_rx_callback pfn_rx_cb,bsp_can_tx_callback pfn_tx_cb)
{
	ASSERT(handle);
	handle->rx_callback = pfn_rx_cb;
	handle->tx_callback = pfn_tx_cb;
	if(handle->hal_can_handle.Instance == FDCAN1)
	{
		HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn,2,2);
		HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
		if(NULL != pfn_rx_cb)
		{
			__HAL_FDCAN_ENABLE_IT(&handle->hal_can_handle,FDCAN_IT_TX_COMPLETE);
		}
		if(NULL != pfn_rx_cb)
		{
			HAL_FDCAN_ActivateNotification(&handle->hal_can_handle,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
		}
	}
	else if(handle->hal_can_handle.Instance == FDCAN2)
	{
		HAL_NVIC_SetPriority(FDCAN2_IT0_IRQn,2,2);
		HAL_NVIC_EnableIRQ(FDCAN2_IT0_IRQn);
		if(NULL != pfn_rx_cb)
		{
			__HAL_FDCAN_ENABLE_IT(&handle->hal_can_handle,FDCAN_IT_TX_COMPLETE);
		}
		if(NULL != pfn_rx_cb)
		{
			HAL_FDCAN_ActivateNotification(&handle->hal_can_handle,FDCAN_IT_RX_FIFO1_NEW_MESSAGE,0);
		}
	}
}

can_err_t bsp_can_close(bsp_can_t* handle)
{
	ASSERT(handle);
//  FDCAN1_FORCE_RESET();
//  FDCAN1_RELEASE_RESET();
//	HAL_NVIC_DisableIRQ(FDCAN2_IT0_IRQn);
	HAL_FDCAN_DeInit(&handle->hal_can_handle);
	return CAN_ERR_NONE;
}
uint8_t bsp_can_recv(bsp_can_t* handle,uint8_t *buff)
{
	ASSERT(handle);
	FDCAN_RxHeaderTypeDef FDCAN_RxHeader;
	if(buff==NULL||HAL_FDCAN_GetRxMessage(&handle->hal_can_handle,FDCAN_RX_FIFO0,&FDCAN_RxHeader,buff)!=HAL_OK)
		return 0;
	return FDCAN_RxHeader.DataLength>>16;	
}
can_err_t bsp_can_send(bsp_can_t* handle,uint16_t dest_can_id, uint8_t *buff,uint8_t len)
{
	ASSERT(handle);
	FDCAN_TxHeaderTypeDef FDCAN_TxHeader;
	FDCAN_TxHeader.Identifier=dest_can_id;
	FDCAN_TxHeader.IdType=FDCAN_STANDARD_ID;
	FDCAN_TxHeader.TxFrameType=FDCAN_DATA_FRAME;
	FDCAN_TxHeader.DataLength=((uint32_t)len) << 16;
	FDCAN_TxHeader.ErrorStateIndicator=FDCAN_ESI_ACTIVE;            
	FDCAN_TxHeader.BitRateSwitch=FDCAN_BRS_OFF;
	FDCAN_TxHeader.FDFormat=FDCAN_CLASSIC_CAN;
	FDCAN_TxHeader.TxEventFifoControl=FDCAN_NO_TX_EVENTS;
	FDCAN_TxHeader.MessageMarker=0;                           
	if(NULL==buff||len==0)
		return CAN_ERR_TX;
	memcpy(m_tx_buf,buff,len);
	if(HAL_FDCAN_AddMessageToTxFifoQ(&handle->hal_can_handle,&FDCAN_TxHeader,m_tx_buf)!=HAL_OK)
		return CAN_ERR_TX;
	return CAN_ERR_NONE;
}
void FDCAN1_IT0_IRQHandler(void)
{
#ifdef RTOS
	rt_interrupt_enter();
#endif
	HAL_FDCAN_IRQHandler(&m_bsp_can1.hal_can_handle);
#ifdef RTOS
	rt_interrupt_leave(); 
#endif	
}
void FDCAN2_IT0_IRQHandler(void)
{
#ifdef RTOS
	rt_interrupt_enter();
#endif
	HAL_FDCAN_IRQHandler(&m_bsp_can2.hal_can_handle);
#ifdef RTOS
	rt_interrupt_leave(); 
#endif	
}
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
	bsp_can_t* handle;
	if(hfdcan->Instance == FDCAN1)
		handle = &m_bsp_can1;
	else if(hfdcan->Instance == FDCAN2)
		handle = &m_bsp_can2;
	uint8_t rx_buff[CAN_MAX_SIZE];
	FDCAN_RxHeaderTypeDef FDCAN_RxHeader;
	HAL_FDCAN_GetRxMessage(hfdcan,FDCAN_RX_FIFO0,&FDCAN_RxHeader,rx_buff);
	if(NULL != handle && handle->rx_callback)
	{
		handle->rx_callback(handle,FDCAN_RxHeader.Identifier,rx_buff,FDCAN_RxHeader.DataLength>>16);
		__HAL_FDCAN_ENABLE_IT(hfdcan,FDCAN_IT_RX_FIFO0_NEW_MESSAGE);
	}
}
void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
	bsp_can_t* handle;
	if(hfdcan->Instance == FDCAN1)
		handle = &m_bsp_can1;
	else if(hfdcan->Instance == FDCAN2)
		handle = &m_bsp_can2;
	uint8_t rx_buff[CAN_MAX_SIZE];
	FDCAN_RxHeaderTypeDef FDCAN_RxHeader;
	HAL_FDCAN_GetRxMessage(hfdcan,FDCAN_RX_FIFO1,&FDCAN_RxHeader,rx_buff);
	if(NULL != handle && handle->rx_callback)
	{
		handle->rx_callback(handle,FDCAN_RxHeader.Identifier,rx_buff,FDCAN_RxHeader.DataLength>>16);
		__HAL_FDCAN_ENABLE_IT(hfdcan,FDCAN_IT_RX_FIFO1_NEW_MESSAGE);
	}
}

void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes)
{
	bsp_can_t* handle;
	if(hfdcan->Instance == FDCAN1)
		handle = &m_bsp_can1;
	else if(hfdcan->Instance == FDCAN2)
		handle = &m_bsp_can2;
	if(NULL != handle && handle->tx_callback)
	{
		handle->tx_callback(handle);
		__HAL_FDCAN_ENABLE_IT(&handle->hal_can_handle,FDCAN_IT_TX_COMPLETE);
	}
}
can_err_t   bsp_can_tx_available(bsp_can_t* handle)
{
	ASSERT(handle);
	
	if((handle->hal_can_handle.Instance->TXBC & FDCAN_TXBC_TFQS) == 0)
	{
		return CAN_ERR_BUSY;
	}
	/* Check that the Tx FIFO/Queue is not full */
	if((handle->hal_can_handle.Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0)
	{
		return CAN_ERR_BUSY;
	}
	return CAN_ERR_NONE;
}